En relation avec la rédaction en cours de la page portail lignes de commande qui est en projet, et avec la page participer au portail sur les lignes de commandes qui vient en appoint pour décharger les contributeurs de la lourde tache du formatage, un programme java a été créé pour générer automatiquement le formatage. Le programme est particulièrement long (400 lignes), mais il a été conçu dans l'optique de la fiabilité et de l'ergonomie. Et plus un programme est ergonomique, plus il est long ;).
Copiez-collez le code source dans un fichier texte que vous nommerez CommandArray.java. Vous avez besoin d'avoir installé le paquet gcj pour pouvoir compiler du java en ligne de commande.
Compilez le programme avec la commande suivante:
javac CommandArray.java
Ensuite en admettant que vous ayez copié collé tous les modèles renseignés de la page participer au portail sur les lignes de commandes dans un fichier nommé commandes.txt, exécutez la commande:
java CommandArray commandes.txt
Le résultat s'affiche à l'écran et est stocké dans le fichier commandes.txt_format.txt
Ce code source est en version 0.1. Il n'a pas encore été beaucoup testé et pourra être sujet à modifications.
/* CommandArray: This program create the formating for the page
* portail_lignes_de_commande of site http://doc.ubuntu-fr.org/
*
* Copyright (C) 2009 Gauthier PERRINEAU
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.LinkedList;
public class CommandArray {
protected static boolean DEBUG = true;
String nom = null;
String description = null;
String lien_synopsys = null;
LinkedList<String> liens = new LinkedList<String>();
String lien_manpage = null;
String lien_forum = null;
public CommandArray(String nom, String description){
this(nom);
this.description= description;
}
private CommandArray(String nom){
this.nom=nom;
}
/**
* @param args
*/
public static void main(String[] args) {
printLicense();
BufferedReader in;
BufferedWriter out;
// check nombre arguments
if(args.length!=1){
printUsage();
return;
}
// check help
if(args[0].equals("-h") || args[0].equals("-help") || args[0].equals("-u") || args[0].equals("-usage")){
printUsage();
return;
}
// check ouverture fichier input
try {
in = new BufferedReader(new FileReader(args[0]));
} catch (FileNotFoundException e) {
println("erreur: nom de fichier incorrect: "+args[0]);
if(DEBUG)
e.printStackTrace();
return;
}
// check ouverture fichier output
String outputFileName = args[0]+"_format.txt";
try {
out = new BufferedWriter(new FileWriter(outputFileName));
} catch (IOException e) {
println("erreur: impossible de créer le fichier d'output: "+outputFileName);
if(DEBUG)
e.printStackTrace();
return;
}
//exécution formatage
println("formating content file: "+args[0]+" to file "+outputFileName+"...");
try {
performFormat(in, out);
} catch (Exception e1) {
println("Une erreur est survenue durant l'exécution");
if(DEBUG)
e1.printStackTrace();
}
finally {
// fermeture des flux
try {
in.close();
out.close();
} catch (IOException e) {
println("Warning: une erreur est survenue pendant la fermeture des fichiers");
if(DEBUG)
e.printStackTrace();
}
}
println("Le programme s'est terminé sans erreurs");
}
public static void performFormat(BufferedReader in,BufferedWriter out) throws IOException, ParseException{
LinkedList<CommandArray> commandListe = readFile(in);
//vérifications d'intégrité
if(!checkCommandListValidity(commandListe))
return;
/**
* A partir de maintenant on dispose d'une liste d'objets ayant au moins un nom et une description probablement valides.
* Les urls sont forcément correctement constituées.
*/
String formatedLine = null;
for(int i=0;i<commandListe.size();i++){
formatedLine = makeFormattedLine(commandListe.get(i));
out.write(formatedLine+"\n");
println(formatedLine);
}
}
/************************************************
* FONCTIONS DE FORMATAGE *
************************************************/
public static String makeFormattedLine(CommandArray commandArray){
StringBuilder result = new StringBuilder();
int i;
//String link = null;
result.append("| ");
result.append(commandArray.description);
result.append(" | ");
result.append(makeDocLinkString(commandArray.lien_synopsys,commandArray.nom));
result.append(" | ");
if(commandArray.liens!=null){
for(i=0;i<commandArray.liens.size()-1;i++)
result.append(makeDocLinkString(commandArray.liens.get(i),null)+", ");
result.append(makeDocLinkString(commandArray.liens.get(i),null));
}
result.append(" | ");
result.append(makeExternLink(commandArray.lien_manpage,"manpage"));
result.append(" | ");
result.append(makeExternLink(commandArray.lien_forum,"forum"));
result.append(" |");
return result.toString();
}
public static String makeDocLinkString(String link, String nom){
String result = null;
URL url = null;
String name = null;
//si le champ correspondant n'a pas été renseigné
if(link==null)
return "";
// devrait pas y avoir de problème
try {url = new URL(link);} catch (MalformedURLException e) {return null;}
//gestion du nom (si le nom donné est invalide, construit un nom par défaut
if(nom!=null)
if(checkValidity(nom))
name=nom;
if(name==null){
name=url.getPath();
int slash = name.lastIndexOf("/");
if(slash!=-1){
name=name.substring(slash+1);
}
}
//gestion du chemin
String path = url.getPath();
char [] pathChar = path.toCharArray();
for(int i=0;i<pathChar.length;i++)
if(pathChar[i]=='/')
pathChar[i]=':';
path = new String(pathChar);
//gestion de l'ancre
String ancre = url.getRef();
if(ancre==null)
ancre="";
if(ancre.indexOf('?')!=-1){
ancre=ancre.substring(0, ancre.indexOf('?')-1);
}
//construction de la représentation de la doc:
result = "[["+path;
if(!ancre.equals(""))
result+="#"+ancre;
result+="|"+name+"]]";
return result;
}
public static String makeExternLink(String link,String nom){
//si le champ correspondant n'a pas été renseigné
if(link==null)
return "";
else
return "[["+link+"|"+nom+"]]";
}
/************************************************
* FONCTIONS DE VERIFICATION DE VALIDITE *
************************************************/
public static boolean checkCommandListValidity(LinkedList<CommandArray> commandListe){
boolean validity = true;
CommandArray commandArray=null;
//taille
if(commandListe.size()==0){
println("erreur, pas d'objet valide trouvé.");
return false;
}
//validité objets
for(int i=0;i<commandListe.size();i++){
commandArray=commandListe.get(i);
if(!checkCommandValidity(commandArray)){
debug("performFormat","warning, lien_forum {"+commandArray.lien_forum+"} incorrect >> Réinitialisé");
commandListe.remove(commandArray);
}
}
//taille
if(commandListe.size()==0){
println("erreur, pas d'objet valide trouvé après check de validité.");
return false;
}
return validity;
}
public static boolean checkCommandValidity(CommandArray commandArray){
boolean result = true;
String lien = null;
if(!checkValidity(commandArray.nom)){
result = false;
debug("checkCommandValidity","erreur, nom {"+commandArray.nom+"} incorrect");
}
if(!checkValidity(commandArray.description)){
result = false;
debug("checkCommandValidity","erreur, description {"+commandArray.description+"} incorrect");
}
if(!checkLinkValidity(commandArray.lien_synopsys)){
commandArray.lien_synopsys=null;
debug("checkCommandValidity","warning, lien_synopsys {"+commandArray.lien_synopsys+"} incorrect >> Réinitialisé");
}
if(!checkLinkValidity(commandArray.lien_manpage)){
commandArray.lien_manpage=null;
debug("checkCommandValidity","warning, lien_manpage {"+commandArray.lien_manpage+"} incorrect >> Réinitialisé");
}
if(!checkLinkValidity(commandArray.lien_forum)){
commandArray.lien_forum=null;
debug("checkCommandValidity","warning, lien_forum {"+commandArray.lien_forum+"} incorrect >> Réinitialisé");
}
if(commandArray.liens.size()==0)
commandArray.liens = null;
else {
for(int i=0;i<commandArray.liens.size();i++){
lien = commandArray.liens.get(i);
if(!checkLinkValidity(lien)){
debug("checkCommandValidity","warning, lien {"+lien+"} incorrect >> Réinitialisé");
commandArray.liens.remove(lien);
}
}
if(commandArray.liens.size()==0)
commandArray.liens = null;
}
return result;
}
public static boolean checkValidity(String arg){
if(arg==null)
return false;
//pas envie de me prendre la tête à faire "si ya que des espaces" ;)
if(arg.equals("") || arg.equals(" ") || arg.equals(" ") || arg.equals(" "))
return false;
if(arg.length()<2)
return false;
return true;
}
public static boolean checkLinkValidity(String arg){
@SuppressWarnings("unused")
URL url = null;
try {
url = new URL(arg);
} catch (MalformedURLException e) {
return false;
}
return true;
}
/************************************************
* FONCTIONS DE LECTURE DU FICHIER SOURCE *
************************************************/
/**
* Crée la liste des commandes à formater à partir du fichie source
* @param in
* @return LinkedList<CommandArray>
* @throws IOException
* @throws ParseException
*/
public static LinkedList<CommandArray> readFile(BufferedReader in) throws IOException, ParseException{
LinkedList<CommandArray> commandListe = new LinkedList<CommandArray>();
/****
* Initialisation. Pour l'initialisation on fait tous les tests de validité possibles, on sera moins strict par la suite.
*/
String [] firstValidLine = searchForValidLine(in);
if(firstValidLine==null)
throw new CommandArray.ParseException("Erreur, aucune ligne valide trouvée dans le fichier.");
if(!firstValidLine[0].equals("NOM"))
throw new CommandArray.ParseException("Erreur, le NOM doit venir en premier " +
"(vérifiez si vous n'avez pas une ligne comportant un ':' précédent " +
"votre première ligne commençant par NOM");
String [] secondValidLine = searchForValidLine(in);
if(!secondValidLine[0].equals("DESCRIPTION"))
throw new CommandArray.ParseException("Erreur, la DESCRIPTION doit venir juste" +
" après le NOM");
if(!checkValidity(firstValidLine[1]))
throw new CommandArray.ParseException("Erreur, nom invalide: {"+firstValidLine[1]+"}");
if(!checkValidity(secondValidLine[1]))
throw new CommandArray.ParseException("Erreur, description invalide: {"+firstValidLine[1]+"}");
CommandArray commandArray = new CommandArray(firstValidLine[1],secondValidLine[1]);
/*******
* Boucle. On ne se soucie pas trop des éventuels problèmes d'objet mal rempli, ce sera checké en aval
*/
String [] line = null;
String arg = null, key = null;
while((line=searchForValidLine(in))!=null){
key = line[0];
arg = line[1];
if(key.equals("NOM")){
commandListe.add(commandArray);
commandArray=new CommandArray(arg);
}
if(key.equals("DESCRIPTION"))
commandArray.description=arg;
if(key.equals("LIEN_SYNOPSIS"))
commandArray.lien_synopsys=arg;
if(key.equals("LIEN"))
commandArray.liens.add(arg);
if(key.equals("LIEN_MANPAGE"))
commandArray.lien_manpage=arg;
if(key.equals("LIEN_FORUM"))
commandArray.lien_forum=arg;
}
commandListe.add(commandArray);
return commandListe;
}
/**
* Retrouve la ligne valide suivante dans le fichier source.
* Une ligne est considérée comme valide si elle comporte un ':'
* @param in
* @return ligne valide
* @throws IOException
*/
public static String [] searchForValidLine(BufferedReader in) throws IOException{
String line = null;
//String key = null;
String [] splitedLine = new String[2];
int doubledotindex=-1;
while((line=in.readLine())!=null){
doubledotindex=line.indexOf(':');
if(doubledotindex!=-1)
{
splitedLine[0]=line.substring(0, doubledotindex);
if(doubledotindex<line.length())
splitedLine[1]=line.substring(doubledotindex+1);
else
splitedLine[1]="";
/*splitedLine = line.split(":");
if(splitedLine.length==2)
return splitedLine;
else {
key = splitedLine[0];
splitedLine=new String[2];
splitedLine[0]=key;
splitedLine[1]="";
return splitedLine;
}*/
return splitedLine;
}
}
return null;
}
/*******************************
* println & debug stuff *
*******************************/
public static void println(String s){
System.out.println(s);
}
public static void println(String [] s){
for(int i=0;i<s.length;i++)
System.out.println(s[i]);
}
public static void debug(String origin,String s){
if (DEBUG) {
System.out.println("DEBUG(FormatArray."+origin+"): "+s);
}
}
public static void debug(String origin,String [] s){
if (DEBUG) {
for (int i = 0; i < s.length; i++)
System.out.println("DEBUG(FormatArray."+origin+"): "+s[i]);
}
}
public static void printUsage(){
println("***************************************************************************");
println("* FormatArray *");
println("***************************************************************************");
println("");
println("génère le formatage correspondant à l'ensemble des commandes fournies dans le ");
println("fichier passé en paramètre:");
println("");
println("paramètre obligatoire: nom du fichier");
println("le résultat est stocké dans le fichier NOM_FICHIER_format.txt");
println("le fichier source doit contenir au moins une fois le motif suivant:");
println("");
println("NOM:");
println("DESCRIPTION:");
println("LIEN_SYNOPSIS:");
println("LIEN:");
println("LIEN_MANPAGE:");
println("LIEN_FORUM:");
println("");
println("Le nombre de LIEN est indifférent. Une entrée valide doit contenir au moins");
println("une DESCRIPTION et un NOM. Si vous ne disposez pas par exemple du LIEN_MANPAGE,");
println("vous pouvez indifféremment mettre la ligne vide ou pas.");
}
public static void printLicense(){
println("FormatArray Copyright (C) 2009 Gauthier PERRINEAU");
println("This program comes with ABSOLUTELY NO WARRANTY; for details visit site http://www.gnu.org/licenses/gpl.html.");
println("This is free software, and you are welcome to redistribute it");
println("under certain conditions; visit site http://www.gnu.org/licenses/gpl.html for details.");
println("");
}
/**
* @author aldian
* Exception dédiée aux problèmes survenus dans l'interprétation du contenu du fichier source.
*/
static class ParseException extends Exception {
private static final long serialVersionUID = -1172968771252448754L;
public ParseException(String erreur){
super (erreur);
}
}
}